import numpy as np
import pandas as pd
import Analysis

def FactorParams():

    factors = {}

    # Profit
    factors["ProfitMargin_OperatingProfit"] = {"Period": "Quarterly"}
    factors["ProfitMargin_OperatingProfit_LYR"] = {"Period": "Quarterly"}
    factors["ProfitMargin_OperatingProfit_TTM"] = {"Period": "Quarterly"}
    #
    factors["ProfitMargin_OperatingProfit1"] = {"Period": "Quarterly"}
    factors["ProfitMargin_OperatingProfit1_LYR"] = {"Period": "Quarterly"}
    factors["ProfitMargin_OperatingProfit1_TTM"] = {"Period": "Quarterly"}
    #
    factors["ProfitMargin_NetIncome2"] = {"Period": "Quarterly"}
    factors["ProfitMargin_NetIncome2_LYR"] = {"Period": "Quarterly"}
    factors["ProfitMargin_NetIncome2_TTM"] = {"Period": "Quarterly"}
    #
    factors["ROE_NetIncome2_LYR"] = {"Period": "Quarterly"}
    factors["ROE_NetIncome2_TTM"] = {"Period": "Quarterly"}
    factors["ROA_NetIncome2_LYR"] = {"Period": "Quarterly"}
    factors["ROA_NetIncome2_TTM"] = {"Period": "Quarterly"}
    #
    factors["ROE_OperatingProfit1_lyr"] = {"Period": "Quarterly"}
    factors["ROE_OperatingProfit1_ttm"] = {"Period": "Quarterly"}
    factors["ROE_OperatingProfit_lyr"] = {"Period": "Quarterly"}
    factors["ROE_OperatingProfit_ttm"] = {"Period": "Quarterly"}
    #
    factors["ROA_OperatingProfit1_LYR"] = {"Period": "Quarterly"}
    factors["ROA_OperatingProfit1_TTM"] = {"Period": "Quarterly"}
    factors["ROA_OperatingProfit_LYR"] = {"Period": "Quarterly"}
    factors["ROA_OperatingProfit_TTM"] = {"Period": "Quarterly"}

    # Earning Variab


    # Valuation
    factors["PB_LF"] = {"Period": "Monthly", "NonNegative": True}
    factors["PS_TTM"] = {"Period": "Monthly", "NonNegative": True}
    factors["PS_LYR"] = {"Period": "Monthly", "NonNegative": True}
    #
    factors["PE_NetIncome2_TTM"] = {"Period": "Monthly", "NonNegative": True}
    factors["PE_NetIncome2_LYR"] = {"Period": "Monthly", "NonNegative": True}
    #
    factors["PE_OperatingProfit1_LYR"] = {"Period": "Monthly", "NonNegative": True}
    factors["PE_OperatingProfit1_TTM"] = {"Period": "Monthly", "NonNegative": True}
    factors["PE_OperatingProfit_LYR"] = {"Period": "Monthly", "NonNegative": True}
    factors["PE_OperatingProfit_TTM"] = {"Period": "Monthly", "NonNegative": True}
    #
    factors["EarningToPrice_TTM"] = {"Period": "Monthly"}
    factors["EarningToPrice_LYR"] = {"Period": "Monthly"}
    factors["BookToMarket"] = {"Period": "Monthly", "NonNegative": True}
    #
    factors["EnterpriseMultiple_R_TTM"] = {"Period": "Monthly"}
    factors["EnterpriseMultiple_R_LYR"] = {"Period": "Monthly"}
    #
    factors["PCF_TTM"] = {"Period": "Monthly", "NonNegative": True}
    factors["PCF_LYR"] = {"Period": "Monthly", "NonNegative": True}
    factors["PCF_R_TTM"] = {"Period": "Monthly"}
    factors["PCF_R_LYR"] = {"Period": "Monthly"}
    #
    factors["PNetCF_TTM"] = {"Period": "Monthly", "NonNegative": True}
    factors["PNetCF_LYR"] = {"Period": "Monthly", "NonNegative": True}
    factors["PNetCF_R_TTM"] = {"Period": "Monthly"}
    factors["PNetCF_R_LYR"] = {"Period": "Monthly"}
    #
    factors["PFCF_TTM"] = {"Period": "Monthly", "R": True, "NonNegative": True}
    factors["PFCF_LYR"] = {"Period": "Monthly", "R": True, "NonNegative": True}

    # Cash flow
    factors["FCFToTotalIncome_LYR"] = {"Period": "Quarterly"}
    factors["FCFToTotalIncome_TTM"] = {"Period": "Quarterly"}
    #
    factors["CashROIC_LYR"] = {"Period": "Quarterly"}
    factors["CashROIC_TTM"] = {"Period": "Quarterly"}
    #
    factors["CashEarningToPrice_LYR"] = {"Period": "Quarterly"}
    factors["CashEarningToPrice_TTM"] = {"Period": "Quarterly"}
    #
    factors["CashEarningToEarning_LYR"] = {"Period": "Quarterly"}
    factors["CashEarningToEarning_TTM"] = {"Period": "Quarterly"}
    #
    factors["CashEarningMinusEarning_LYR"] = {"Period": "Quarterly"}
    factors["CashEarningMinusEarning_TTM"] = {"Period": "Quarterly"}

    # Growth
    factors["Growth_CAGR_EPS_1Yr"] = {"Period": "Quarterly"}
    factors["Growth_CAGR_EPS_3Yr"] = {"Period": "Quarterly"}
    factors["Growth_CAGR_EPS_5Yr"] = {"Period": "Quarterly"}
    #
    factors["Growth_CAGR_FreeCashFlow_1Yr"] = {"Period": "Quarterly"}
    factors["Growth_CAGR_FreeCashFlow_3Yr"] = {"Period": "Quarterly"}
    factors["Growth_CAGR_FreeCashFlow_5Yr"] = {"Period": "Quarterly"}
    #
    factors["Growth_CAGR_NetIncome2_1Yr"] = {"Period": "Quarterly"}
    factors["Growth_CAGR_NetIncome2_3Yr"] = {"Period": "Quarterly"}
    factors["Growth_CAGR_NetIncome2_5Yr"] = {"Period": "Quarterly"}
    #
    factors["Growth_CAGR_TotalAsset_1Yr"] = {"Period": "Quarterly"}
    factors["Growth_CAGR_TotalAsset_3Yr"] = {"Period": "Quarterly"}
    factors["Growth_CAGR_TotalAsset_5Yr"] = {"Period": "Quarterly"}
    #
    # Equity_CAGR
    factors["Growth_CAGR_TotalEquity_1Yr"] = {"Period": "Quarterly"}
    factors["Growth_CAGR_TotalEquity_3Yr"] = {"Period": "Quarterly"}
    factors["Growth_CAGR_TotalEquity_5Yr"] = {"Period": "Quarterly"}
    #
    factors["Growth_CAGR_TotalRevenue_1Yr"] = {"Period": "Quarterly"}
    factors["Growth_CAGR_TotalRevenue_3Yr"] = {"Period": "Quarterly"}
    factors["Growth_CAGR_TotalRevenue_5Yr"] = {"Period": "Quarterly"}
    #
    factors["Growth_CAGR_OperatingProfit1_1Yr"] = {"Period": "Quarterly"}
    factors["Growth_CAGR_OperatingProfit1_3Yr"] = {"Period": "Quarterly"}
    factors["Growth_CAGR_OperatingProfit1_5Yr"] = {"Period": "Quarterly"}
    #
    factors["Growth_CAGR_OperatingProfit_1Yr"] = {"Period": "Quarterly"}
    factors["Growth_CAGR_OperatingProfit_3Yr"] = {"Period": "Quarterly"}
    factors["Growth_CAGR_OperatingProfit_5Yr"] = {"Period": "Quarterly"}
    #
    factors["Growth_CAGR_Sales_1Yr"] = {"Period": "Quarterly"}

    # ProfitMargin_CAGR
    factors["Growth_CAGR_ProfitMargin_OperatingProfit1_1Yr"] = {"Period": "Quarterly"}
    factors["Growth_CAGR_ProfitMargin_OperatingProfit1_3Yr"] = {"Period": "Quarterly"}
    factors["Growth_CAGR_ProfitMargin_OperatingProfit1_5Yr"] = {"Period": "Quarterly"}
    #
    factors["Growth_CAGR_ProfitMargin_OperatingProfit_1Yr"] = {"Period": "Quarterly"}
    factors["Growth_CAGR_ProfitMargin_OperatingProfit_3Yr"] = {"Period": "Quarterly"}
    factors["Growth_CAGR_ProfitMargin_OperatingProfit_5Yr"] = {"Period": "Quarterly"}
    #
    # FCF_CAGR
    factors["Growth_CAGR_OperatingCashFlow_1Yr"] = {"Period": "Quarterly"}
    factors["Growth_CAGR_OperatingCashFlow_3Yr"] = {"Period": "Quarterly"}
    factors["Growth_CAGR_OperatingCashFlow_5Yr"] = {"Period": "Quarterly"}
    #
    # ROE_CAGR
    factors["Growth_CAGR_ROE_1Yr"] = {"Period": "Quarterly"}
    factors["Growth_CAGR_ROE_3Yr"] = {"Period": "Quarterly"}
    factors["Growth_CAGR_ROE_5Yr"] = {"Period": "Quarterly"}
    #
    factors["Growth_YoY_EPS"] = {"Period": "Quarterly"}
    factors["Growth_YoY_NetIncome2"] = {"Period": "Quarterly"}
    factors["Growth_YoY_OperatingProfit"] = {"Period": "Quarterly"}
    factors["Growth_YoY_OperatingProfit1"] = {"Period": "Quarterly"}
    factors["Growth_YoY_ProfitMargin_OperatingProfit"] = {"Period": "Quarterly"}
    factors["Growth_YoY_ProfitMargin_OperatingProfit1"] = {"Period": "Quarterly"}
    factors["Growth_YoY_ROE"] = {"Period": "Quarterly"}
    factors["Growth_YoY_TotalRevenue"] = {"Period": "Quarterly"}
    #
    # Leverage / Capital
    factors["Leverage"] = {"Period": "Quarterly"}
    factors["CapLeverage"] = {"Period": "Quarterly"}
    factors["BookLeverage"] = {"Period": "Quarterly"}
    factors["DebtToAsset"] = {"Period": "Quarterly"}
    #
    factors["CurrentAssetToAsset"] = {"Period": "Quarterly"}
    factors["CurrentRatio"] = {"Period": "Quarterly"}
    # factors["CurrentRatio_LYR"] = {"Period": "Quarterly"}
    factors["QuickRatio"] = {"Period": "Quarterly"}

    # Opreation
    factors["AssetTurnover_LYR"] = {"Period": "Quarterly"}
    factors["AssetTurnover_TTM"] = {"Period": "Quarterly"}
    #
    factors["FixedAssetTurnover_LYR"] = {"Period": "Quarterly"}
    factors["FixedAssetTurnover_TTM"] = {"Period": "Quarterly"}
    #
    factors["CurrentAssetTurnover_LYR"] = {"Period": "Quarterly"}
    factors["CurrentAssetTurnover_TTM"] = {"Period": "Quarterly"}
    factors["InventoryTurnover_LYR"] = {"Period": "Quarterly"}
    factors["InventoryTurnover_TTM"] = {"Period": "Quarterly"}
    factors["ReceivableTurnover_LYR"] = {"Period": "Quarterly"}
    factors["ReceivableTurnover_TTM"] = {"Period": "Quarterly"}

    # MScore
    factors["AccrualsToTotalAsset_lYr"] = {"Period": "Quarterly"}
    factors["AssetQuality_Index"] = {"Period": "Quarterly"}
    factors["DaysSaleRecv_Index"] = {"Period": "Quarterly"}
    factors["Depreciation_Index"] = {"Period": "Quarterly"}
    factors["Grossmargin_Index"] = {"Period": "Quarterly"}
    factors["SGA_Index"] = {"Period": "Quarterly"}
    factors["Leverage_Index"] = {"Period": "Quarterly"}
    factors["MScore_Experience"] = {"Period": "Quarterly"}

    # Price Momentum
    factors["CAPMAlpha_Annually"] = {"Period": "Monthly"}
    factors["Momentum_20D"] = {"Period": "Monthly"}
    factors["Bias_20D"] = {"Period": "Monthly"}
    factors["MA5ToMA10"] = {"Period": "Monthly"}

    # Size
    factors["Cap"] = {"Period": "Monthly"}
    factors["LnCap"] = {"Period": "Monthly"}
    factors["CirculatingToTotalCap"] = {"Period": "Monthly"}
    factors["Equity"] = {"Period": "Quarterly"}
    factors["TotalAsset"] = {"Period": "Quarterly"}
    factors["NetIncome2"] = {"Period": "Quarterly"}
    factors["OCF"] = {"Period": "Quarterly"}
    factors["NetCF"] = {"Period": "Quarterly"}

    # Volatility
    factors["CAPMBeta_Annually"] = {"Period": "Monthly"}
    factors["Volatility_Annually"] = {"Period": "Monthly"}
    factors["Volatility_HighLow"] = {"Period": "Monthly"}
    factors["IdioValotility_CAPM"] = {"Period": "Monthly"}
    factors["IdioValotility_FF3"] = {"Period": "Monthly"}

    # Liquidity
    factors["Liquidity20D"] = {"Period": "Monthly"}
    factors["LiquidityQ"] = {"Period": "Monthly"}
    factors["LiquidityAnnully"] = {"Period": "Monthly"}
    factors["Turnover20D"] = {"Period": "Monthly"}

    # Misc
    factors["HolderCR10"] = {"Period": "Monthly"}

    # Trade Activity

    # Dividend Yield

    # Holdings
    factors["Holding_MF_Chg_LYR"] = {"Period": "ReportDate"}
    factors["Holding_MF_Chg_YoY"] = {"Period": "ReportDate"}
    factors["Holding_MF_Chg_LF"] = {"Period": "ReportDate"}
    #
    factors["Holding_MF_Diff_LYR"] = {"Period": "ReportDate"}
    factors["Holding_MF_Diff_YoY"] = {"Period": "ReportDate"}
    factors["Holding_MF_Diff_LF"] = {"Period": "ReportDate"}
    #
    factors["Holding_MF_RatioChg_LYR"] = {"Period": "ReportDate"}
    factors["Holding_MF_RatioChg_YoY"] = {"Period": "ReportDate"}
    factors["Holding_MF_RatioChg_LF"] = {"Period": "ReportDate"}
    #
    factors["Holding_MF_RatioDiff_LYR"] = {"Period": "ReportDate"}
    factors["Holding_MF_RatioDiff_YoY"] = {"Period": "ReportDate"}
    factors["Holding_MF_RatioDiff_LF"] = {"Period": "ReportDate"}

    # Sentiment
    factors["Xueqiu_Follows_Diff_Weekly"] = {"Period": "Weekly"}
    factors["Xueqiu_Follows_Diff_Monthly"] = {"Period": "Monthly"}

    # Analyst
    factors["analyst_con_or_yoy_roll"] = {"Period": "Monthly"}
    factors["analyst_con_np_yoy_roll"] = {"Period": "Monthly"}
    factors["analyst_con_np_diff_roll"] = {"Period": "Monthly"}
    factors["analyst_con_or_diff_roll"] = {"Period": "Monthly"}
    factors["analyst_con_eps_diff_roll"] = {"Period": "Monthly"}
    factors["analyst_con_pe_diff_roll"] = {"Period": "Monthly"}
    factors["analyst_con_pb_diff_roll"] = {"Period": "Monthly"}

    for key, value in factors.items():
        factors[key]["Name"] = key
        # factors[key.lower()] = factors[key]

    return factors


def ProcessFactors(df):
    # ---Delete Dirty---
    df.replace([np.inf, -np.inf], np.nan, inplace=True)
    df.dropna(inplace=True)

    #
    factors = FactorParams()

    #
    dfRemerge = pd.DataFrame()
    fields = df.columns
    for factorName in fields:
        if factorName == "Symbol":
            continue
        param = factors.get(factorName)
        if param == None:
            print("ProcessFactors: Factor No Params", factorName)
            continue
        #
        dfTemp = df[["Symbol", factorName]]
        dfTemp = ProcessFactor(dfTemp, factorName, param)
        if dfRemerge.empty:
            dfRemerge = dfTemp
        else:
            dfRemerge = pd.merge(left=dfRemerge, right=dfTemp, on="Symbol", how="inner")

    # print(data_df.describe())
    return dfRemerge


def ProcessFactor(df, factorName, params, processOutlier=False):
    # ---General Process---
    df.replace([np.inf, -np.inf], np.nan, inplace=True)
    df.dropna(inplace=True)
    notNegative = False
    ascending = True
    outlier = 0.025
    reciprocal = False

    # ---Reciprocal---
    if params.get("R"):
        df[factorName] = 1 / df[factorName]

    # ---Outlier---
    if params.get("Outlier"):
        outlier = params.get("Outlier")
    if processOutlier:
        Analysis.PreProcess.Outlier_Percentile(df, outlier, 1-outlier)

    # ---Special Process---
    if params.get("NonNegative"):
        df = df[df[factorName] > 0]
        # df[df[field] < 0][field] = 0

    # ---log---
    if params.get("Log"):
        # data_df['SalePrice'] = np.log1p(data_df['SalePrice'])
        # numeric_features = list(data_df.columns)
        # numeric_features.remove('SalePrice')
        pass

    # ---Sorting---
    # if params.get("Desc"):
    #     ascending = False
    # df.sort_values(by="Value", ascending=ascending, inplace=True)

    #
    # print(df)
    return df